import uuid
from common_tools import get_logger_with_trace_id
from flask import Flask, request, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_bcrypt import Bcrypt
from flask_httpauth import HTTPBasicAuth
from project_model import db
from global_scope import (
    PROJECT_NAME, DB_INFO, set_db, SECRET_KEY, set_auth, set_bcrypt,
    BCRYPT_HASH_PREFIX, BCRYPT_HANDLE_LONG_PASSWORDS, LOGGER, TRACE_LOGGER,
    MAX_CONTENT_LENGTH, UPLOAD_FOLDER
)
from global_scope import set_limiter


def create_app() -> Flask:
    """
    创建并配置Flask应用。

    :return: 配置好的Flask应用实例
    """

    app_instance = Flask(PROJECT_NAME)
    app_instance.logger = get_logger_with_trace_id("appLevelLog", TRACE_LOGGER)

    @app_instance.before_request
    def before_request():
        """
        在每个请求之前执行，生成traceId并配置日志记录器。
        """
        trace_id = str(uuid.uuid4())
        request.trace_id = trace_id
        request.logger = get_logger_with_trace_id(trace_id, LOGGER)
        request.trace_logger = get_logger_with_trace_id(trace_id, TRACE_LOGGER)

    limiter = Limiter(
        get_remote_address,
        app=app_instance,
        default_limits=["50000 per day", "3000 per hour"]
    )
    set_limiter(limiter)

    @app_instance.errorhandler(429)
    def ratelimit_handler(e):
        return jsonify({
            "code": 1,
            "message": "ratelimit exceeded %s" % e.description,
            "data": None,
            "originUrl": request.url
        }), 429

    configure_app(app_instance)
    initialize_db(app_instance)
    return app_instance


def configure_app(app_instance: Flask):
    """
    配置Flask应用的各项设置。

    :param app_instance: Flask应用实例
    """
    app_instance.config['SQLALCHEMY_DATABASE_URI'] = DB_INFO
    app_instance.config['SQLALCHEMY_ECHO'] = False
    app_instance.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app_instance.config['SECRET_KEY'] = SECRET_KEY
    app_instance.config['BCRYPT_HASH_PREFIX'] = BCRYPT_HASH_PREFIX
    app_instance.config['BCRYPT_HANDLE_LONG_PASSWORDS'] = BCRYPT_HANDLE_LONG_PASSWORDS
    app_instance.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER  # 文件上传路径
    app_instance.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH  # 限制文件大小为 16 MB


def initialize_db(app_instance: Flask):
    """
    初始化数据库。

    :param app_instance: Flask应用实例
    """
    try:
        db.init_app(app_instance)
        set_db(db)
        bcrypt = Bcrypt(app_instance)
        auth = HTTPBasicAuth()
        set_bcrypt(bcrypt)
        set_auth(auth)
    except Exception as e:
        app_instance.logger.error(f"Database initialization failed: {e}")


app = create_app()
